﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using WebAPITest.Models.Database;

namespace WebAPITest.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class CacheController : ControllerBase
    {
        private readonly IMemoryCache cache;
        private readonly WebEnterpriseIIContext _db;

        ///<summary>
        ///构造注入从ioc容器去除 缓存服务
        /// </summary>
        /// <param name="cache"></param>
        public CacheController(IMemoryCache cache,WebEnterpriseIIContext db)
        {
            this.cache = cache;
            //key /value
            //key 是字符串 缓存数据的名字
            //value 是值
            _db = db;
        }

        /// <summary>
        /// 判断缓存是否存在
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<string> TryGetValueCache()
        {
            //方法名：TryGetValue("key",可返回的变量)
            //out(可返回的变量）string（返回变量的类型） username（返回变量的名字）
            if (cache.TryGetValue("UserName", out string username)) {
                return "该缓存存在"+username;
            }
            else {
                return "该缓存不存在";
            }
        }



        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<string> SetCache()
        {
            return cache.Set("UserName", "Hriluom");
        }


        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<string> GetCache()
        {
            return cache.Get<string>("UserName");
        }

        /// <summary>
        /// 读写缓存
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<string> GetOrCreateCache()
        {
            string userName = cache.GetOrCreate("UserName", entry =>
            {
                return "admin";
            });
            string password = cache.GetOrCreate("Password", entry =>
            {
                return "12345";
            });
            return userName + "\n" + password;
        }   
        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<string> RemoveCache()
        {
            cache.Remove("UserName");
            return "缓存删除成功";
        }

        /// <summary>
        /// 永不过期
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<string> cachetime()
        {
            string msg = string.Empty;
            cache.Set("UserName", "admin");
            for (int i =1; i <= 5; i++) {
                msg += $"第{i}秒缓存值：{cache.Get<string>("UserName")}\n";
                Thread.Sleep(1000);
            }
            return msg;
        }

        /// <summary>
        /// 绝对时间过期
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<string> CacheTime2()
        {
            string msg = string.Empty;
            cache.Set("UserName", "admin", TimeSpan.FromSeconds(3));

            // 读取缓存
            for (int i = 1; i <= 5; i++) {
                msg += $"第{i}秒缓存值：{cache.Get<string>("UserName")}\n";
                Thread.Sleep(1000);
            }

            // 返回
            return msg;
        }


        /// <summary>
        /// 滑动时间过期
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<string> CacheTime3()
        {
            string msg = string.Empty;
            cache.Set("UserName", "admin", new MemoryCacheEntryOptions {
                //滑动时间过期
                //在三秒内如果有人访问，则自动刷新变成三秒
                //如果三秒内没人访问则删除缓存
                SlidingExpiration = TimeSpan.FromSeconds(0.5)
            });

            // 读取缓存
            for (int i = 1; i <= 5; i++) {
                msg += $"第{i}秒缓存值：{cache.Get<string>("UserName")}\n";
                Thread.Sleep(1000);
            }

            // 返回
            return msg;
        }

        /// <summary>
        /// 绝对时间过期+滑动时间过期
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<string> Get()
        {
            string msg = string.Empty;
            cache.Set("UserName", "admin", new MemoryCacheEntryOptions {
                SlidingExpiration = TimeSpan.FromSeconds(1.5),
                //滑动时间或者绝对时间其中一种发生之后，触发缓存消失
                AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(3)
            });

            // 读取缓存
            for (int i = 1; i <= 5; i++) {
                msg += $"第{i}秒缓存值：{cache.Get<string>("UserName")}\n";
                Thread.Sleep(1000);
            }

            // 返回
            return msg;
        }
        /// <summary>
        /// 编写接口获取商品列表数据，并且使用本地缓存保存查询结果，缓存时间为30分钟
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [ResponseCache(Duration = 5)]
        public List<Good> GetGoodsList()
        {

            //return _db.Goods.ToList();
            return cache.GetOrCreate("Goods", List => {
                return _db.Goods.ToList();
            });
        }
        /// <summary>
        /// 编写商品详情接口，用户浏览商品详情时使用本地缓存保存登录用户浏览商品记录
        /// </summary>
        /// <param name="goodid"></param>
        /// <returns></returns>
        [HttpGet]
        [Authorize]
        public Good GetGoodinfo(int goodid)
        {
            var good=_db.Goods.FirstOrDefault(x => x.Id == goodid);
            //使用本地缓存保存登录用户流浪的商品记录（多个商品）
            var userID = Response.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
            //获取当前用户下之前查看过的商品缓存记录 每个用户都有自己缓存列表 用字符串拼接的方式进行定义；
            var record = cache.Get<List<Good>>($"UserViews{userID}");
            //定义一个列表集，并将当前浏览的商品信息存进去
            var views = new List<Good>();
            views.Add(good);
            //将之前浏览的信息放在一起
            if (record != null) {
                views.AddRange(record);
            }
            cache.Set($"UserViews{userID}", views);
            return good;
        }
    }
}
